package org.adorsys.aderp.jpa.api.audit;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.Enumerated;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.roo.addon.javabean.RooJavaBean;

/**
 * This is the audit record must be extended concrete classes to 
 * provide storage space for audit logs.
 * 
 * @author francis
 *
 */
@RooJavaBean
@MappedSuperclass
public class AbstractAuditRecord implements Comparable<AbstractAuditRecord> {

	/**
	 * The business key of the audit record. This is in general a
	 * combination between the business key of the entity and the 
	 * modification timestamp.
	 */
    private String recordKey;

    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "dd-MM-yyyy HH:mm:ss")
    private Date modifOn;

    /**
     * This is the business key of the modifying user.
     */
    @NotNull
    private String modifyingUser;

    /**
     * This is the business key of the entity modified.
     * 
     * We don't recommend hard references of entities. Use entity business key and
     * entityName for soft references.
     */
    @NotNull
    private String entityKey;

    /**
     * This is the name of the entity modified. Redundant information,
     * because each entity store audit log in a proper table. But some
     * data tools might want to merge logs for analysis purpose.
     */
    @NotNull
    private String entityName;

    /**
     * Type of modification done.
     */
    @NotNull
    @Enumerated
    private ModifMode modifMode = ModifMode.CREATED;
    
    /**
     * Any additional data of interest.
     */
    private String envData;

	public String getRecordKey() {
		return recordKey;
	}

	public void setRecordKey(String recordKey) {
		this.recordKey = recordKey;
	}

	public Date getModifOn() {
		return modifOn;
	}

	public void setModifOn(Date modifOn) {
		this.modifOn = modifOn;
	}

	public String getModifyingUser() {
		return modifyingUser;
	}

	public void setModifyingUser(String modifyingUser) {
		this.modifyingUser = modifyingUser;
	}

	public String getEntityKey() {
		return entityKey;
	}

	public void setEntityKey(String entityKey) {
		this.entityKey = entityKey;
	}

	public String getEntityName() {
		return entityName;
	}

	public void setEntityName(String entityName) {
		this.entityName = entityName;
	}

	public ModifMode getModifMode() {
		return modifMode;
	}

	public void setModifMode(ModifMode modifMode) {
		this.modifMode = modifMode;
	}

	public String getEnvData() {
		return envData;
	}

	public void setEnvData(String envData) {
		this.envData = envData;
	}

	@Override
	public int compareTo(AbstractAuditRecord ar) {
		return modifMode.compareTo(ar.getModifMode());
	}
    
	public static final String RECORDKEY_MAPKEY = "recordKey";
	public static final String MODIFON_MAPKEY = "modifOn";
	public static final String MODIFYINGUSER_MAPKEY = "modifyingUser";
	public static final String ENTITYKEY_MAPKEY = "entityKey";
	public static final String ENTITYNAME_MAPKEY = "entityName";
	public static final String MODIFMODE_MAPKEY = "modifMode";
	
	public Map<String, String> toDataMap(){
		Map<String, String> result = new HashMap<String, String>();
		result.put(RECORDKEY_MAPKEY, recordKey);
		result.put(ENTITYKEY_MAPKEY, entityKey);
		result.put(MODIFON_MAPKEY, ""+ modifOn.getTime());
		result.put(MODIFYINGUSER_MAPKEY, modifyingUser);
		result.put(ENTITYNAME_MAPKEY, entityName);
		result.put(MODIFMODE_MAPKEY, modifMode.name());
		return result;
	}

	public void fromDataMap(Map<String, String> data) {
		this.recordKey = data.get(RECORDKEY_MAPKEY);
		
		this.entityKey = data.get(ENTITYKEY_MAPKEY);
		
		String mfo = data.get(MODIFON_MAPKEY);
		if(mfo!=null)
			this.modifOn = new Date(Long.valueOf(mfo));

		this.modifyingUser = data.get(MODIFYINGUSER_MAPKEY);
		
		this.entityName = data.get(ENTITYNAME_MAPKEY);
		
		String mmd = data.get(MODIFMODE_MAPKEY);
		if(mmd!=null)
			this.modifMode = ModifMode.valueOf(mmd);
	}	
    
}
